//Copyright (C) 2002 Microsoft Corporation
//All rights reserved.
//THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER 
//EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF 
//MERCHANTIBILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
//Requires the Trial or Release version of Visual Studio .NET Professional (or greater).

using System;
using System.IO;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Text;

public class frmMain : System.Windows.Forms.Form
{

#region " Windows Form Designer generated code "

	/// <summary>
	/// The main entry point for the application.
	/// </summary>
	[STAThread]
	static void Main() 
	{
		Application.Run(new frmMain());
	}

    public frmMain()
	{
        //This call is required by the Windows Form Designer.
        InitializeComponent();
        //Add any initialization after the InitializeComponent() call
        // So that we only need to set the title of the application once,
        // we use the AssemblyInfo class (defined in the AssemblyInfo.cs file)
        // to read the AssemblyTitle attribute.
        AssemblyInfo ainfo = new AssemblyInfo();
        this.Text = ainfo.Title;
        this.mnuAbout.Text = string.Format("&About {0} ...", ainfo.Title);
    }

    //Form overrides dispose to clean up the component list.
    protected override void Dispose(bool disposing) {
        if (disposing) {
            if (components != null) {
                components.Dispose();
            }
        }
        base.Dispose(disposing);
    }
    //Required by the Windows Form Designer
    private System.ComponentModel.IContainer components = null;
    //NOTE: The following procedure is required by the Windows Form Designer
    //It can be modified using the Windows Form Designer.  
    //Do not modify it using the code editor.
    private System.Windows.Forms.MainMenu mnuMain;

    private System.Windows.Forms.MenuItem mnuFile;

    private System.Windows.Forms.MenuItem mnuExit;

    private System.Windows.Forms.MenuItem mnuHelp;

    private System.Windows.Forms.MenuItem mnuAbout;

    private System.Windows.Forms.TabControl TabControl1;

    private System.Windows.Forms.TextBox txtDisplay;

    private System.Windows.Forms.TextBox txtSend;

    private System.Windows.Forms.Button btnSend;

    private System.Windows.Forms.TabPage tpChatPage;

    private System.Windows.Forms.TabPage tpListUsers;

    private System.Windows.Forms.ListBox lstUsers;

    private System.Windows.Forms.Button btnListUsers;

    private System.Windows.Forms.Label lblInstructions;

    private System.Windows.Forms.Label Label1;

    private void InitializeComponent() {
        this.components = new System.ComponentModel.Container();
        System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmMain));
        this.mnuMain = new System.Windows.Forms.MainMenu(this.components);
        this.mnuFile = new System.Windows.Forms.MenuItem();
        this.mnuExit = new System.Windows.Forms.MenuItem();
        this.mnuHelp = new System.Windows.Forms.MenuItem();
        this.mnuAbout = new System.Windows.Forms.MenuItem();
        this.TabControl1 = new System.Windows.Forms.TabControl();
        this.tpChatPage = new System.Windows.Forms.TabPage();
        this.lblInstructions = new System.Windows.Forms.Label();
        this.btnSend = new System.Windows.Forms.Button();
        this.txtSend = new System.Windows.Forms.TextBox();
        this.txtDisplay = new System.Windows.Forms.TextBox();
        this.tpListUsers = new System.Windows.Forms.TabPage();
        this.Label1 = new System.Windows.Forms.Label();
        this.btnListUsers = new System.Windows.Forms.Button();
        this.lstUsers = new System.Windows.Forms.ListBox();
        this.TabControl1.SuspendLayout();
        this.tpChatPage.SuspendLayout();
        this.tpListUsers.SuspendLayout();
        this.SuspendLayout();
        // 
        // mnuMain
        // 
        this.mnuMain.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.mnuFile,
            this.mnuHelp});
        // 
        // mnuFile
        // 
        this.mnuFile.Index = 0;
        this.mnuFile.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.mnuExit});
        resources.ApplyResources(this.mnuFile, "mnuFile");
        // 
        // mnuExit
        // 
        this.mnuExit.Index = 0;
        resources.ApplyResources(this.mnuExit, "mnuExit");
        this.mnuExit.Click += new System.EventHandler(this.mnuExit_Click);
        // 
        // mnuHelp
        // 
        this.mnuHelp.Index = 1;
        this.mnuHelp.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.mnuAbout});
        resources.ApplyResources(this.mnuHelp, "mnuHelp");
        // 
        // mnuAbout
        // 
        this.mnuAbout.Index = 0;
        resources.ApplyResources(this.mnuAbout, "mnuAbout");
        this.mnuAbout.Click += new System.EventHandler(this.mnuAbout_Click);
        // 
        // TabControl1
        // 
        this.TabControl1.Controls.Add(this.tpChatPage);
        this.TabControl1.Controls.Add(this.tpListUsers);
        resources.ApplyResources(this.TabControl1, "TabControl1");
        this.TabControl1.Name = "TabControl1";
        this.TabControl1.SelectedIndex = 0;
        // 
        // tpChatPage
        // 
        resources.ApplyResources(this.tpChatPage, "tpChatPage");
        this.tpChatPage.Controls.Add(this.lblInstructions);
        this.tpChatPage.Controls.Add(this.btnSend);
        this.tpChatPage.Controls.Add(this.txtSend);
        this.tpChatPage.Controls.Add(this.txtDisplay);
        this.tpChatPage.Name = "tpChatPage";
        // 
        // lblInstructions
        // 
        resources.ApplyResources(this.lblInstructions, "lblInstructions");
        this.lblInstructions.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(192)))));
        this.lblInstructions.Name = "lblInstructions";
        // 
        // btnSend
        // 
        resources.ApplyResources(this.btnSend, "btnSend");
        this.btnSend.Name = "btnSend";
        this.btnSend.Click += new System.EventHandler(this.btnSend_Click);
        // 
        // txtSend
        // 
        resources.ApplyResources(this.txtSend, "txtSend");
        this.txtSend.Name = "txtSend";
        // 
        // txtDisplay
        // 
        resources.ApplyResources(this.txtDisplay, "txtDisplay");
        this.txtDisplay.BackColor = System.Drawing.SystemColors.Window;
        this.txtDisplay.ForeColor = System.Drawing.SystemColors.WindowText;
        this.txtDisplay.Name = "txtDisplay";
        this.txtDisplay.ReadOnly = true;
        this.txtDisplay.TextChanged += new System.EventHandler(this.txtDisplay_TextChanged);
        // 
        // tpListUsers
        // 
        resources.ApplyResources(this.tpListUsers, "tpListUsers");
        this.tpListUsers.Controls.Add(this.Label1);
        this.tpListUsers.Controls.Add(this.btnListUsers);
        this.tpListUsers.Controls.Add(this.lstUsers);
        this.tpListUsers.Name = "tpListUsers";
        // 
        // Label1
        // 
        resources.ApplyResources(this.Label1, "Label1");
        this.Label1.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(192)))));
        this.Label1.Name = "Label1";
        // 
        // btnListUsers
        // 
        resources.ApplyResources(this.btnListUsers, "btnListUsers");
        this.btnListUsers.Name = "btnListUsers";
        this.btnListUsers.Click += new System.EventHandler(this.btnListUsers_Click);
        // 
        // lstUsers
        // 
        resources.ApplyResources(this.lstUsers, "lstUsers");
        this.lstUsers.Name = "lstUsers";
        // 
        // frmMain
        // 
        resources.ApplyResources(this, "$this");
        this.Controls.Add(this.TabControl1);
        this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
        this.MaximizeBox = false;
        this.Menu = this.mnuMain;
        this.Name = "frmMain";
        this.Closing += new System.ComponentModel.CancelEventHandler(this.frmMain_Closing);
        this.Load += new System.EventHandler(this.frmMain_Load);
        this.TabControl1.ResumeLayout(false);
        this.tpChatPage.ResumeLayout(false);
        this.tpChatPage.PerformLayout();
        this.tpListUsers.ResumeLayout(false);
        this.ResumeLayout(false);

	}

#endregion

#region " Standard Menu Code "

    // This code simply shows the About form.
    private void mnuAbout_Click(object sender, System.EventArgs e) {
        // Open the About form in Dialog Mode
        frmAbout frm = new frmAbout();
        frm.ShowDialog(this);
        frm.Dispose();
    }

    // This code will close the form.
    private void mnuExit_Click(object sender, System.EventArgs e) {
        // Close the current form
        this.Close();
    }

#endregion

    const int READ_BUFFER_SIZE = 255;
    const int PORT_NUM = 10000;
    private TcpClient client;
	private byte[] readBuffer = new byte[READ_BUFFER_SIZE];
  
    // Pop up a Connect user dialog and send a message requesting user to log in to chat.
    void AttemptLogin()
	{
        frmConnectUser frmConnectUser = new frmConnectUser();
        frmConnectUser.StartPosition = FormStartPosition.CenterParent;
        frmConnectUser.ShowDialog(this);
        SendData("CONNECT|" + frmConnectUser.txtUserLogin.Text);
        frmConnectUser.Dispose();
    }

    // Clear the Users listbox, and request the server to send the list of users.
    private void btnListUsers_Click(object sender, System.EventArgs e) 
	{
        lstUsers.Items.Clear();
        SendData("REQUESTUSERS");
    }

    // Send the contents of the Send textbox if it isn't blank.
    private void btnSend_Click(object sender, System.EventArgs e)
	{
        if (txtSend.Text != "") 
		{
            DisplayText("You say: " + txtSend.Text + (char) 13 + (char) 10);
            SendData("CHAT|" + txtSend.Text);
            txtSend.Text = string.Empty;
        }
    }

    // Writes text to the output textbox.
    private void DisplayText(string text)
	{
        txtDisplay.AppendText(text);
    }

    // This is the callback function for TcpClient.GetStream.Begin to get an
    // asynchronous read.
    private void DoRead(IAsyncResult ar)
	{
        int BytesRead;
        string strMessage;

        try
		{
            // Finish asynchronous read into readBuffer and return number of bytes read.
            BytesRead = client.GetStream().EndRead(ar);
            if (BytesRead < 1) {
                // if no bytes were read server has close.  Disable input window.
                MarkAsDisconnected();
                return;
            }
            // Convert the byte array the message was saved into, minus two for the
            // Chr(13) and Chr(10)
            strMessage = Encoding.ASCII.GetString(readBuffer, 0, BytesRead - 2);
            ProcessCommands(strMessage);
            // Start a new asynchronous read into readBuffer.
            client.GetStream().BeginRead(readBuffer, 0, READ_BUFFER_SIZE, new AsyncCallback(DoRead), null);

       } 
		catch( Exception e)
		{
            MarkAsDisconnected();
        }
    }

    // Send the server a disconnect message  
    private void frmMain_Closing(object sender, System.ComponentModel.CancelEventArgs e) //base.Closing;
	{
        // Send only if server is still running.
        if (btnSend.Enabled == true)
		{
            SendData("DISCONNECT");
        }
    }

    // When the form starts, this subroutine will connect to the server and attempt to
    // log in.
    private void frmMain_Load(object sender, System.EventArgs e) 
	{
        frmConnectUser frmConnectUser = new frmConnectUser();
        try 
		{
            // The TcpClient is a subclass of Socket, providing higher level 
            // functionality like streaming.
            client = new TcpClient("localhost", PORT_NUM);
            // Start an asynchronous read invoking DoRead to avoid lagging the user
            // interface.
            client.GetStream().BeginRead(readBuffer, 0, READ_BUFFER_SIZE, new AsyncCallback(DoRead), null);
            // Make sure the window is showing before popping up connection dialog.
            this.Show();
            AttemptLogin();
       } 
		catch( Exception Ex)
		{
            MessageBox.Show("Server is not active.  Please start server and try again.",
                   this.Text,MessageBoxButtons.OK , MessageBoxIcon.Exclamation);
            this.Dispose();
        }
    }

    // This subroutine adds a list of users to listbox.
    private void ListUsers(string[] users)
	{
        int I;

        for (I = 1; I <= (users.Length - 1); I++)
		{
            lstUsers.Items.Add(users[I]);
        }
    }

    // When the server disconnects, prevent further chat messages from being sent.
    private void MarkAsDisconnected()
	{
        txtSend.ReadOnly = true;
        btnSend.Enabled = false;
    }

    // Process the command received from the server, and take appropriate action.
    private void ProcessCommands(string strMessage)
	{
        string[] dataArray;
        // Message parts are divided by "|"  Break the string into an array accordingly.
        dataArray = strMessage.Split((char) 124);
        // dataArray(0) is the command.
        switch( dataArray[0])
		{
            case "JOIN":
                // Server acknowledged login.
                DisplayText("You have joined the chat" + (char) 13 + (char) 10);
				break;
            case "CHAT":
                // Received chat message, display it.
                DisplayText(dataArray[1] + (char) 13 + (char) 10);
				break;
            case "REFUSE":
                // Server refused login with this user name, try to log in with another.
                AttemptLogin();
				break;
            case "LISTUSERS":
                // Server sent a list of users.
                ListUsers(dataArray);
				break;
            case "BROAD":
                // Server sent a broadcast message
                DisplayText("ServerMessage: " + dataArray[1] + (char) 13 + (char) 10);
				break;
        }
    }

    // Use a StreamWriter to send a message to server.
    private void SendData(string data)
	{
        StreamWriter writer = new StreamWriter(client.GetStream());
        writer.Write(data + (char) 13);
        writer.Flush();
    }

    private void txtDisplay_TextChanged(object sender, EventArgs e)
    {

    }
}

